package com.video.filter;

import com.video.constants.SysConstants;
import com.video.entity.User;
import com.video.exception.SystemException;
import com.video.result.AppHttpCodeEnum;
import com.video.utils.JwtUtil;
import com.video.utils.RedisCache;
import com.video.entity.LoginUser;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @author LZH
 * @date 2023/3/29
 */
@Slf4j
@Component
public class LoginFilter extends OncePerRequestFilter {

    //路径匹配器,AntPathMatcher是spring的一个用于路径匹配的工具类
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    @Resource
    private RedisCache redisCache;

    @Resource
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.debug("-----------------执行了登陆过滤器");

        String requestURI = request.getRequestURI();
        log.info("获取请求信息：" + requestURI);
        //过滤路径，设置不过滤的请求
        String[] urls = {
                "/user/login",
                "/user/register",
                "/v2/**",
                "/webjars/**",
                "/swagger-resources/**",
                "swagger-ui.html",
                "/doc.html",
                "/vlogs/{id}",
                "/tag/pageVlogs/{tagId}/{pageNum}/{pageSize}",
                "/comment/{vlogId}"
        };
        boolean check = check(requestURI, urls);
        //白名单请求则放行
        if (check) {
            filterChain.doFilter(request, response);
            return;
        }

        String token = request.getHeader("token");

        if (StringUtils.hasText(token)) {
            Claims claims = null;
            try {
                claims = JwtUtil.parseJWT(token);
                String userId = claims.getSubject();
                LoginUser loginUser = redisCache.getCacheObject(SysConstants.USER_LOGIN + userId);
                User user = loginUser.getUser();
                if (Objects.isNull(user)) {
                    resolver.resolveException(request, response, null, new SystemException(AppHttpCodeEnum.USER_NOT_LOGIN));
                }
                filterChain.doFilter(request, response);
                return;
            } catch (Exception e) {
                resolver.resolveException(request, response, null, new SystemException(AppHttpCodeEnum.USER_NOT_LOGIN));
            }
        }

        resolver.resolveException(request, response, null, new SystemException(AppHttpCodeEnum.USER_NOT_LOGIN));
    }

    public boolean check(String requestURI, String[] urls) {
        for (int i = 0; i < urls.length; i++) {
            //match方法用于匹配路径，确定路径是否一致，相同返回true，不同返回false
            boolean match = PATH_MATCHER.match(urls[i], requestURI);
            if (match) {
                return true;
            }
        }
        return false;
    }
}
